# (1)
# 题目描述：
# 通过OpenCV读取一张图片，完成下面的操作：1、滤波
# 2、二值化
# 3、轮廓发现
# 4、轮廓绘制5、凸包检测
# 6、在轮廓周围绘制正矩形7、在轮廓周围绘制旋转矩形8、在轮廓周围绘制圆9、在轮廓周围绘制椭圆10、求出每个轮廓的中心点11、计算每个轮廓的面积12、计算每个轮廓的周长
#
# (2)
# 题目要求：.
# ①　导入相关头文件
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

spr = 2
spc = 4
spn = 0
plt.figure(figsize=(12, 6))


def my_show_img(img, title, trans=None, **kwargs):
    global spn
    spn += 1
    plt.subplot(spr, spc, spn)
    if trans is not None:
        img = trans(img)
    plt.title(title)
    plt.axis('off')
    plt.imshow(img, **kwargs)


# ②　滤波
img = cv.imread('data/balloons.png', cv.IMREAD_GRAYSCALE)
H, W = img.shape
print(f'img.shape: {img.shape}')
img = cv.blur(img, (5, 5))
my_show_img(img, 'After blur', cmap='gray')

# ③　二值化
ret, bin = cv.threshold(img, 127, 255, cv.THRESH_BINARY_INV)
my_show_img(bin, 'bin', cmap='gray')

# ④　轮廓发现
contours, hierarchy = cv.findContours(bin, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

# ⑤　轮廓绘制
bg = np.zeros((H, W), dtype=np.uint8)
bg = cv.drawContours(bg, contours, -1, 255, 2)
my_show_img(bg, 'bg', cmap='gray')

# 找出几个最长轮廓
len_arr = []
for c in contours:
    len_c = cv.arcLength(c, True)
    len_arr.append(len_c)
max_idx_arr = np.argsort(len_arr)[::-1][:5]
print(max_idx_arr)

# ⑥　凸包检测
# ⑦　在轮廓周围绘制正矩形
bgr = cv.cvtColor(bg, cv.COLOR_GRAY2BGR)
for idx in max_idx_arr:
    c = contours[idx]
    x, y, w, h = cv.boundingRect(c)
    cv.rectangle(bgr, (x, y), (x + w, y + h), (0, 255, 0), 2)
my_show_img(bgr, 'rectangles', lambda x: cv.cvtColor(x, cv.COLOR_BGR2RGB))

# ⑧　在轮廓周围绘制旋转矩形
# ⑨　在轮廓周围绘制圆
for idx in max_idx_arr:
    c = contours[idx]
    (x, y), r = cv.minEnclosingCircle(c)
    cv.circle(bgr, np.int32((x, y)), int(r), (0, 0, 255), 2)
my_show_img(bgr, 'circles', lambda x: cv.cvtColor(x, cv.COLOR_BGR2RGB))

# ⑩　在轮廓周围绘制椭圆

# 11　求出每个轮廓的中心点
# 12　计算每个轮廓的面积
# 13　计算每个轮廓的周长
for c in contours:
    len_c = cv.arcLength(c, True)
    area_c = cv.contourArea(c)
    moment_c = cv.moments(c)
    cx, cy = 0, 0
    if not np.isclose(moment_c['m00'], 0):
        cx = moment_c['m10'] / moment_c['m00']
        cy = moment_c['m01'] / moment_c['m00']
    print(f'中心点{(cx, cy)}, 面积{area_c}, 周长{len_c}')
